package com.gw.smscheck.controller.business.map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gw.smscheck.entity.business.positionInfo.PositionArea;
import com.gw.smscheck.entity.business.positionInfo.PositionNow;
import com.gw.smscheck.entity.business.positionInfo.PositionTrajectory;
import com.gw.smscheck.service.business.positionInfo.PositionAreaService;
import com.gw.smscheck.service.business.positionInfo.PositionInfoService;
import com.gw.smscheck.service.business.positionInfo.PositionNowService;
import com.gw.smscheck.service.business.positionInfo.PositionTrajectoryService;
import com.gw.smscheck.util.MapUtil;
import com.gw.smscheck.util.ResultObj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/map")
@ApiIgnore
/**
 * @program: MapController
 * @description: 地图的控制类
 * @author: jiangbo
 * @create: 2018-10-30 16:20
 */
public class MapController {
    @Autowired
    private PositionInfoService positionInfoService;
    @Autowired
    private PositionNowService positionNowService;
    @Autowired
    private PositionTrajectoryService positionTrajectoryService;
    @Autowired
    private PositionAreaService positionAreaService;

    /** 
    * @Description: 地图轨迹跳转 
    * @Param:  
    * @return:  
    * @Author: jiangbo
    * @Date: 2018/11/8 0008 
    */ 
    @RequestMapping("/trajectory")
    public ModelAndView goMapTrajectory(String phoneNum,String time) {

        ModelAndView mv = new ModelAndView("views/mapApplication/mapTrajectory");
        if (phoneNum != null&& phoneNum!="") {
            mv.addObject("phoneNum", phoneNum);
        }
        if (time != null&& time!="") {
            mv.addObject("time", time);
        }
        return mv;
    }
   /** 
   * @Description: 轨迹预判跳转 
   * @Param:  
   * @return:  
   * @Author: jiangbo
   * @Date: 2018/11/8 0008 
   */ 
    @RequestMapping("/predict")
    public ModelAndView goMapPredict(String phoneNum,String time) {

        ModelAndView mv = new ModelAndView("views/mapApplication/mapPredict");
        if (phoneNum != null&& phoneNum!="") {
            mv.addObject("phoneNum", phoneNum);
        }
        if (time != null&& time!="") {
            mv.addObject("time", time);
        }
        return mv;
    }

    /**
     * @Description:按照条件进行查询出对应的人员最新的数据-
     * @Param: []
     * @return: java.lang.String
     * @Author: jiangbo
     * @Date: 2018/10/30 0030
     */
    @RequestMapping(value = "getPositionNowList", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public String getPositionNowList(PositionNow position) {

        List<PositionNow> positionNowList =
                positionNowService.findPositionNow(position);
        if(position.getArea()!=null&&position.getArea()!=""){
             PositionArea positionArea= positionAreaService.findByName(position.getArea());
            positionNowList= MapUtil.isPtInPolyMany(positionArea.getBoundary(),positionNowList);
        }
        return ResultObj.successResultObj(positionNowList);
    }

    /**
     * @Description:按照条件进行查询出对应的人员的轨迹数据
     * @Param: []
     * @return: java.lang.String
     * @Author: jiangbo
     * @Date: 2018/10/30 0030
     */
    @RequestMapping(value = "getPositionTrajectoryList", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public String getPositionTrajectoryList(PositionTrajectory positionTrajectory) {

        List<PositionTrajectory> positionTrajectoryList = positionTrajectoryService.findPositionTrajectory(positionTrajectory);
        return ResultObj.successResultObj(positionTrajectoryList);
    }

    /**
     * 传入区域，判断标注是否在区域，并范围标注信息
     */
    @RequestMapping(value = "isPtInPoly", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public String isPtInPoly(HttpServletRequest request, PositionNow position) {
        //区域的坐标区域
        List<Point2D.Double> pts = new ArrayList<>();
        String geo = request.getParameter("geo");
        JSONArray jsonArray = JSON.parseArray(geo);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject json = JSON.parseObject(jsonArray.getString(i));
            System.out.println(json.getString("lng") + "," + json.getString("lat"));
            pts.add(new Point2D.Double(Double.parseDouble(json.getString("lng")), Double.parseDouble(json.getString("lat"))));
        }

        System.out.println(geo);
        //获取当前地图中的人员标注坐标，来判断是否在区域内
        List<PositionNow> positionNowList = positionNowService.findPositionNow(position);
        int N = pts.size();
        //定义返回的信息
        List<Point2D.Double> returnList = new ArrayList<>();//返回的坐标
        List<PositionNow> returnListNowList = new ArrayList<>();
        //循环判断人员是否在区域之内
        for (PositionNow obj : positionNowList) {
            Point2D.Double point = new Point2D.Double(obj.getLng(), obj.getLat());
            boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
            int intersectCount = 0; // cross points count of x
            double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
            Point2D.Double p1, p2; // neighbour bound vertices
            Point2D.Double p = point; // 当前点
            p1 = pts.get(0); // left vertex
            for (int i = 1; i <= N; ++i) { // check all rays
                if (p.equals(p1)) {
                    returnList.add(p);
                    returnListNowList.add(obj);
                }

                p2 = pts.get(i % N); // right vertex
                if (p.x < Math.min(p1.x, p2.x)
                        || p.x > Math.max(p1.x, p2.x)) { // ray is outside of our interests
                    p1 = p2;
                    continue; // next ray left point
                }

                if (p.x > Math.min(p1.x, p2.x)
                        && p.x
                        < Math.max(p1.x, p2.x)) { // ray is crossing over by the algorithm (common part of)
                    if (p.y <= Math.max(p1.y, p2.y)) { // x is before of ray
                        if (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) { // overlies on a horizontal ray
                            returnList.add(p);
                            returnListNowList.add(obj);
                        }

                        if (p1.y == p2.y) { // ray is vertical
                            if (p1.y == p.y) { // overlies on a vertical ray
                                returnList.add(p);
                                returnListNowList.add(obj);
                            } else { // before ray
                                ++intersectCount;
                            }
                        } else { // cross point on the left side
                            double xinters =
                                    (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y; // cross point of y
                            if (Math.abs(p.y - xinters) < precision) { // overlies on a ray
                                returnList.add(p);
                                returnListNowList.add(obj);
                            }

                            if (p.y < xinters) { // before ray
                                ++intersectCount;
                            }
                        }
                    }
                } else { // special case when ray is crossing through the vertex
                    if (p.x == p2.x && p.y <= p2.y) { // p crossing over p2
                        Point2D.Double p3 = pts.get((i + 1) % N); // next vertex
                        if (p.x >= Math.min(p1.x, p3.x)
                                && p.x <= Math.max(p1.x, p3.x)) { // p.x lies between p1.x & p3.x
                            ++intersectCount;
                        } else {
                            intersectCount += 2;
                        }
                    }
                }
                p1 = p2; // next ray left point
            }


            if (intersectCount % 2 == 0) { // 偶数在多边形外

            } else { // 奇数在多边形内
                returnList.add(p);
                returnListNowList.add(obj);
            }
        }
        //直接返回在区域内的重点人员
        return ResultObj.successResultObj(returnListNowList);
    }
}
